-- Lua IRC Bot
-- A skeleton for an IRC Bot, coded in Lua.
-- Contributors: bahamete

require 'socket'

--** Settings ->
local NICK = "LuaBot"
local USER = "LuaBot"
local NAME = "Lua Bot. http://code.google.com/bahamete-tas"

local HOST = "irc.freenode.net"
local PORT = 6667
local CHAN = "#yourchannel"


local response = {}
local irc = { ["host"] = HOST, ["port"] = PORT, ["chan"] = CHAN }
local bot = { ["nick"] = NICK, ["user"] = USER, ["name"] = NAME }

--** String functions

local printf = function(format, ...)
  print(string.format(format, ...))
end

string.startswith = function(str, sub)
  local len = sub:len()
  if str:sub(1, len) == sub then
    return (true)
  end
  return (false)
end

string.trim = function(str, char)
  while str:sub(1, char:len()) ~= char and str:len() > 1 do
    str = str:sub(2, -1)
  end
  return str:sub(2, -1)
end

--** IRC Functions

irc.connect = function(host, port)
  irc.connection, irc.status = socket.connect(host, port)
  irc.connected = true
end

irc.send = function(msg)
--  local msg = msg:format(format, ...)
  irc.connection:send(msg .. "\r\n")
  local msg = msg:startswith("PRIVMSG") and msg:sub(2, -1):trim(':') or msg
  printf("[%s] <%s> %s",
          os.date("%H:%M:%S"),
          bot.nick,
          msg)
end

irc.say = function(format, ...)
  irc.send( "PRIVMSG " .. string.format(format, ...))
end

irc.join = function(chan)
  irc.send("JOIN " .. chan)
end

irc.auth = function()
  irc.send("NICK " .. bot.nick)
  irc.send("USER " .. bot.user .. " 0 * :" .. bot.name)
end


--** Responses and functions to handle them

response.get = function()
  return irc.connection:receive()
end

response.handle = function(msg)
  -- Respond to ping requests
  if msg:sub(1, 4) == "PING" then
    irc.send(msg:gsub("PING", "PONG"))
  end

  -- Join channel when available
  if msg:find("End of /MOTD command.") then
    irc.join(irc.chan)
  end

  -- Get nick from the message
  local pos = msg:find('!')
  response.nick = pos and msg:sub(2, pos - 1) or "Server"

  -- Trim all information before second :
  -- which is all server information.
  response.clean = msg:sub(2, -1):trim(':')
end

local function Main()
  -- TODO: Make this a controller while loop
  if not irc.connected then
    irc.connect(irc.host, irc.port)
  end

  irc.auth()

  while irc.connected and irc.status ~= "timeout" and status ~= "closed" do
    response.raw = response.get()

    if response.raw ~= "" then
      response.handle(response.raw)

      if response.clean ~= "" then
        printf("[%s] <%s> %s",
                os.date("%H:%M:%S"),
                response.nick,
                response.clean)
      end
    end
  end

  irc.connected = false; collectgarbage();
  return Main()
end

printf("Beginning connection to %s:%s.",
        irc.host,
        irc.port)
Main()
